package me.android.library.utils.android.wifi;

import android.Manifest;
import android.annotation.SuppressLint;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Build;

import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresPermission;

import com.google.common.collect.Lists;

import java.util.List;
import java.util.Objects;

import lombok.Getter;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import me.android.library.utils.android.NetworkUtil;
import me.android.library.utils.android.SystemServiceUtil;


@Slf4j
@UtilityClass
@RequiresApi(api = Build.VERSION_CODES.R)
public class WifiUtil {

    final String LOCK_MULTICAST = "lock_multicast";
    MulticastLock multicastLock;
    List<ScanResult> scanResults = Lists.newArrayList();

    @Getter
    WifiConfig wifiConfig = new WifiConfig(){};
    @Getter
    WifiConnector wifiConnector = new WifiConnector(){};
    @Getter
    WifiScanner wifiScanner = new WifiScanner() {
        @Override
        public List<ScanResult> getScanResult() {
            return scanResults;
        }
    };


    /**
     * wifi是否可用
     */
    public boolean isEnabled() {
        return getWifiManager().isWifiEnabled();
    }

    /**
     * wifi状态
     */
    public int getWifiState() {
        return getWifiManager().getWifiState();
    }

    /**
     * wifi是否连接
     */
    public boolean isWifiConnected() {
        return NetworkUtil.isConnectedToWiFi();
    }

    /**
     * 比较ssid是否相等
     */
    public boolean isSameSSID(String ssid1, String ssid2) {
        if (ssid1 == null || ssid2 == null) return false;
        String Format = "\"%s\"";

        String str1 = String.format(Format, ssid1);
        String str2 = String.format(Format, ssid2);
        return ssid1.equals(ssid2) || ssid1.equals(str2) || str1.equals(ssid2) || str1.equals(str2);
    }

    /**
     * 是否加密
     */
    public boolean isEncrypted(ScanResult sr) {
        WifiCipherType type = getCipherType(sr);
        return Objects.equals(type, WifiCipherType.OPEN);
    }

    /**
     * 打开WIFI
     */
    public void openWifi() {
        getWifiManager().setWifiEnabled(true);
    }

    /**
     * 关闭WIFI
     */
    public void closeWifi() {
        getWifiManager().setWifiEnabled(false);
    }

    /**
     * 允许组播 android 组播需要先解锁，费电
     * 需要权限：android.permission.CHANGE_WIFI_MULTICAST_STATE
     */
    public void allowMulticast() {
        if (multicastLock == null) {
            multicastLock = getWifiManager().createMulticastLock(LOCK_MULTICAST);
            multicastLock.acquire();
        }
    }

    /**
     * 禁用组播
     */
    public void disableMulticast() {
        if (multicastLock != null && multicastLock.isHeld()) {
            multicastLock.release();
            multicastLock = null;
        }
    }

    /**
     * 获取网络安全性
     */
    public WifiCipherType getCipherType(ScanResult result) {
        if (result.capabilities.contains("WEP")) {
            return WifiCipherType.WPA_PSK;
        } else if (result.capabilities.contains("PSK")) {
            return WifiCipherType.WPA2_PSK;
        } else if (result.capabilities.contains("SAE")) {
            return WifiCipherType.WPA3_SAE;
        }
        return WifiCipherType.OPEN;
    }

    /**
     * 获取当前连接的wifiInfo
     */
    public WifiInfo getConnectionInfo() {
        return getWifiManager().getConnectionInfo();
    }

    @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION)
    public ScanResult getScanResultBySsid(String ssid) {
        List<ScanResult> list = getScanResults();
        if (list != null) {
            return list.stream().filter(sr -> isSameSSID(ssid, sr.SSID)).findFirst().orElse(null);
        }
        return null;
    }

    @SuppressLint("MissingPermission")
    @RequiresPermission(allOf = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})
    public List<ScanResult> getScanResults() {
        return getWifiManager().getScanResults();
    }

    private WifiManager getWifiManager() {
        return SystemServiceUtil.getWifiManager();
    }
}
